<?php
// Copyright 2019 Hackware SpA <human@hackware.cl>
// This file is part of "Hackware Web Services Wallet" and licensed under
// the terms of the GNU Affero General Public License version 3, or (at your
// option) a later version. You should have received a copy of this license
// along with the software. If not, see <https://www.gnu.org/licenses/>.

namespace Hawese\Wallet\Http\Controllers;

use Hawese\Wallet\Currency;
use Hawese\Wallet\Transaction;
use Hawese\Core\Http\Controllers\Controller;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class TransactionController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function store(Request $request)
    {
        $this->authorize('create', Transaction::class);

        $data = json_decode($request->getContent(), true);

        if (array_values($data) === $data) { // Is bulk / non-associative
            $transactions = $this->bulkStore($data);
            // Send emails only if it's all right with the entire batch
            foreach ($transactions as $transaction) {
                $transaction->emailNotification();
            }
            return $transactions;
        } else {
            $transaction = $this->singleStore($data);
            $transaction->emailNotification();
            return $transaction;
        }
    }

    protected function singleStore(array $transaction_data): Transaction
    {
        if (empty($transaction_data['currency_id'])) {
            $transaction_data['currency_id'] = Currency::findByCode(
                $transaction_data['currency_code']
            )->id;
        }

        $transaction_data = Arr::only($transaction_data, [
            'user_uid', 'currency_id', 'amount', 'type', 'description', 'detail'
        ]);

        $transaction = new Transaction($transaction_data);
        if (!empty($transaction_data['detail'])) {
            $transaction->detail = $transaction_data['detail'];
        }
        $transaction->insert();
        return $transaction;
    }


    protected function bulkStore(array $transactions_data): array
    {
        return app('db')->transaction(function () use ($transactions_data) {
            $processed_transactions = [];
            foreach ($transactions_data as $transaction_data) {
                array_push(
                    $processed_transactions,
                    $this->singleStore($transaction_data)
                );
            }
            return $processed_transactions;
        });
    }

    /**
     * List current user transactions
     *
     * Unless superuser, which can list everyone's or filter by user_uid.
     */
    public function index(Request $request)
    {
        return $this->collectionResponse(
            $request,
            Transaction::class,
            function ($transactions) use ($request) {
                if (!$request->user()->isSuperUser()) {
                    $transactions->where(
                        ['user_uid' => $request->user()->uid]
                    );
                } elseif ($request->has('user_uid')) {
                    $transactions->where([
                        'user_uid' => $request->query('user_uid')
                    ]);
                }

                if ($request->has('start')) {
                    $transactions->where(
                        'created_at',
                        '>=',
                        new Carbon($request->query('start'))
                    );
                }

                if ($request->has('end')) {
                    $end = $request->query('end');
                    if (preg_match('/^[-\d.\/]{10}$/', $end)) {
                        $end .= ' 23:59:59';
                    }

                    $transactions->where(
                        'created_at',
                        '<=',
                        new Carbon($end)
                    );
                }

                if ($request->has('due')) {
                    if ($request->query('due') == 'false') {
                        $transactions->whereNull('due_at');
                    } else {
                        $transactions->whereNotNull('due_at');
                    }
                }

                return $transactions;
            }
        );
    }
}
